/*
* Copyright (c) 2007, Nubo Technologies
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
*    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*    * Neither the name of the Nubo Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.nubotech.gwt.oss.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 
 * Holds an representation of an S3 Object. An Object consists of data and metadata.
 * @author jonnakkerud
 */
public class ObjectHolder {
    /**
     * An empty object
     */
    public static final ObjectHolder EMPTY = new ObjectHolder();
        
    private Bucket bucket;    
    private String key;
    private Date lastModified;
    private int size = -1;
    private Object data;
    private String stringData;
    private String eTag;
    
    private String contentType = "text/plain";
    private Map metaData;
    
    private int accessPolicy = -1;

    /**
     * Returns the Bucket that this object is contained in
     * @return the bucket
     */
    public Bucket getBucket() {
        return bucket;
    }

    /**
     * Sets the bucket that this object is contained in
     * @param bucket the bucket
     */
    public void setBucket(Bucket bucket) {
        this.bucket = bucket;
    }
    
    /**
     * Returns the key for the object. A key is the unique identifier for an object within a bucket.
     * @return the key
     */
    public String getKey() {
        return key;
    }

    /**
     * Sets the key that identifies the object in the bucket. Must be unique.
     * @param key the key
     */
    public void setKey(String key) {
        this.key = key;
    }

    /**
     * Returns that last modified date
     * @return last modified date
     */
    public Date getLastModified() {
        return lastModified;
    }

    /**
     * Set the last modified date
     * @param lastModified last modified date
     */
    public void setLastModified(Date lastModified) {
        this.lastModified = lastModified;
    }

    /**
     * Return the size of the data
     * @return data size
     */
    public int getSize() {
        if (size == -1) {
            size = (data == null ? 0 : sizeof(getDataAsString()));
        }
        return size;
    }

    /**
     * sets the size of the data
     * @param size data size
     */
    public void setSize(int size) {
        this.size = size;
    }

    /**
     * Return the data as an object
     * @return data object
     */
    public Object getData() {
        return data;
    }

    /**
     * Sets the data as an object
     * @param data the data object
     */
    public void setData(Object data) {
        this.data = data;
    }

    /**
     * Return the content type. By default the content type is text/plain
     * @return the content type
     */
    public String getContentType() {
        return this.contentType;
    }

    /**
     * Sets the content type
     * @param contentType the content type
     */
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    /**
     * Returns the meta data for this object
     * @return the meta data
     */
    public Map getMetaData() {
        if (metaData == null) {
            metaData = new HashMap();
        }
        return metaData;
    }
    
    /**
     * sets the meta data
     * @param metaData the meta data
     */
    public void setMetaData(Map metaData) {
        this.metaData = metaData;
    }
    
    /**
     * Adds a meta data name and value that will be stored with the object
     * @param name the meta data name
     * @param value the meta data value
     */
    public void addMetaData(String name, String value) {
        getMetaData().put(name, value);
    }
    
    /**
     * return the data as a string
     * @return data string
     */
    public String getDataAsString() {      
        if (data != null && stringData == null) {
            stringData = data.toString();
        }
        
        return stringData;
    }

    private int sizeof(String data) {
        return data.length();
    }
    
    /**
     * returns if this object has data.
     * @return return true if this object has data
     */
    public boolean hasData() {
        return (this.data != null);
    }
    
    /**
     * returns if this object has meta data
     * @return return true if this object has meta data
     */
    public boolean hasMetaData() {
        return (this.metaData != null && this.metaData.size() > 0);
    }
    
    /**
     * Returns the AccessPolicy for this object
     * @return The access policy
     */
    public int getAccessPolicy() {
        return accessPolicy;
    }

    /**
     * Set the AccessPolicy for the object
     * @param accessPolicy the access policy
     */
    public void setAccessPolicy(int accessPolicy) {
        this.accessPolicy = accessPolicy;
    }

    /**
     * Return the ETag
     * @return the ETag
     */
    public String getETag() {
        return eTag;
    }

    /**
     * Set the ETag
     * @param eTag the etag
     */
    public void setETag(String eTag) {
        this.eTag = eTag;
    }
        
    /**
     * Returns information about this Object
     * @return information about the Object
     */
    public String toStringExt() {
        StringBuffer sb = new StringBuffer();
        sb.append("bucket:").append(this.getBucket().getName()).append("\n");
        sb.append("key:").append(getKey()).append("\n");
        sb.append("data:").append(getDataAsString()).append("\n");
        sb.append("access-policy:").append(getAccessPolicy()).append("\n");
        sb.append("meta-data:\n");
        Iterator itr = getMetaData().keySet().iterator();
        while(itr.hasNext()) {
            String key = (String)itr.next();
            sb.append("\t").append("name:").append(key).append("|value=").append(getMetaData().get(key)).append("\n");
        }
        return sb.toString();
    }


}
